﻿using CommonUtils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Security.Cryptography;
using System.Text;

namespace CommonUtils
{
    public static class EncryptHelper
    {
        //remove log in the official version
        static Log _log = new Log("EncryptHelper", false);
        
        static string iv = "0892029207920300";

        static int[] Root_Key_LIST = {
            0xc8, 0x37, 0x00, 0x5e, 0xbb, 0x99, 0x4a, 0xba,
            0xa4, 0x14, 0xe9, 0xa8, 0xec, 0xa9, 0x23, 0xf1,
            0x87, 0x22, 0xb9, 0x95, 0xec, 0x47, 0x17, 0x85,
            0xee, 0xac, 0x76, 0xe2, 0x53, 0x2b, 0x4c, 0x50,
            0x89, 0x91, 0xf4, 0x09, 0x68, 0xff, 0x6f, 0x48,
            0xa4, 0x34, 0xe9, 0xe2, 0x53, 0x2b, 0x4c, 0x50,
            0x36, 0x23, 0x50, 0x42, 0xac, 0x76, 0xe2, 0x4c,
            0xed, 0x8e, 0x36, 0x23, 0x50, 0x42, 0x4c, 0x44,
        };

        static byte[] getRootKey()
        {
            var firstKey = getKey(Root_Key_LIST);
            //string packageName = "HTC-Sense*Link";
            //var secondKey = stringToKey(packageName, firstKey);
            //var thirdKey = Encrypt(PLEASE_DONT_READ, secondKey);
            //var fourthKey = stringToKey(thirdKey, firstKey);

            return firstKey;
        }

        static byte[] getKey(int[] sourceArray)
        {
            byte[] data = new byte[16];
            for (int i = 0; (i < Root_Key_LIST.Count()); i++)
            {
                data[i % data.Count()] ^= (byte)sourceArray[i];
            }
            return data;
        }


        public static string Encrypt(string toEncrypt)
        {
            if (string.IsNullOrEmpty(toEncrypt)) return string.Empty;
      
            return Encrypt(toEncrypt, getRootKey());
        }

        public static string Decrypt(string toDecrypt)
        {
            try
            {
                if (string.IsNullOrEmpty(toDecrypt)) return string.Empty;
                
                return Decrypt(toDecrypt, getRootKey());
            }
            catch (Exception ex)
            {
                _log.E(ex);
            }
            return string.Empty;
        }

        public static string Encrypt(string toEncrypt, byte[] keyArray)
        {
            if (string.IsNullOrEmpty(toEncrypt)) return string.Empty;
            if (keyArray == null || keyArray.Count() == 0) return string.Empty;

            try
            {
                byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
                byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

                RijndaelManaged rDel = new RijndaelManaged();
                rDel.BlockSize = 128;
                rDel.KeySize = 256;
                rDel.FeedbackSize = 128;
                rDel.Padding = PaddingMode.PKCS7;
                rDel.Key = keyArray;
                rDel.IV = ivArray;
                rDel.Mode = CipherMode.CBC;

                ICryptoTransform cTransform = rDel.CreateEncryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                string newValue = Convert.ToBase64String(resultArray, 0, resultArray.Length);
                _log.I("Original:{0}\r\nNew:{1}", toEncrypt, newValue);
                return newValue;
            }
            catch (Exception ex)
            {
                _log.E(ex);
            }
            return string.Empty;
        }

        private static string Decrypt(string toDecrypt, byte[] keyArray)
        {
            if (string.IsNullOrEmpty(toDecrypt)) return string.Empty;

            try
            {
                byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
                byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

                RijndaelManaged rDel = new RijndaelManaged();

                rDel.BlockSize = 128;
                rDel.KeySize = 256;
                rDel.FeedbackSize = 128;
                rDel.Padding = PaddingMode.PKCS7;
                rDel.Key = keyArray;
                rDel.IV = ivArray;
                rDel.Mode = CipherMode.CBC;
                ICryptoTransform cTransform = rDel.CreateDecryptor();

                byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                string newValue = UTF8Encoding.UTF8.GetString(resultArray);

                _log.I("Original:{0}\r\nNew:{1}", toDecrypt, newValue);
                return newValue;
            }
            catch (Exception ex)
            {
                _log.E(ex);
            }
            return string.Empty;
        }
    }
}
